/*
 * Copyright (c) 2019 Winner Microelectronics Co., Ltd.
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2022-10-31     yuanzihao    first implementation
 */

#include <rtthread.h>
#include <rtdevice.h>
#include <fal.h>
#include <time.h>
#include <ext_gpio_control_thread.h>
#include <work_mode_thread.h>

#define THREAD_PRIORITY 20
#define THREAD_STACK_SIZE 512
#define THREAD_TIMESLICE 5

ALIGN(RT_ALIGN_SIZE)
static char work_mode_thread_stack[1024];
static struct rt_thread work_mode_thread;
static uint8_t __work_mode = WORK_MODE_SHOW_TIME; // 默认为显示时间模式

RT_USED static rt_timer_t work_mode_timer;
RT_USED static uint8_t temp_count = 0;

static pomodoro_data_t pomodoro;
static uint8_t _count_num = 0;
static uint8_t _show_time_mode = WORK_MODE_SHOW_TIME_HOUR; // 在显示时间模式下默认为显示小时模式

static rt_timer_t second_flickers_timer;
static rt_timer_t anti_posion_timer;

static void nixie_tube_anti_posion(struct tm *p);
static void set_pomodoro_to_default(void);
static void work_mode_in_pomodoro(void);
static void work_mode_in_num_counter(void);
static void work_mode_in_show_time(void);
void change_work_mode_in_show_time(void);

/* 线程 work_mode_thread 入口 */
static void work_mode_entry(void *param)
{
    time_t _timep;
    struct tm *_p;
    static _show_time_count = 0;

    set_pomodoro_to_default();
    while (1)
    {
        time(&_timep);
        _p = localtime(&_timep);
        nixie_tube_anti_posion(_p);
        switch (__work_mode)
        {
        case WORK_MODE_POMODORO:
            work_mode_in_pomodoro();
            break;
        case WORK_MODE_NUM_COUNTER:
            work_mode_in_num_counter();
            break;
        case WORK_MODE_SHOW_TIME:
            work_mode_in_show_time();
            break;
        case WORK_MODE_NONE:
            break;
        default:
            log_e(" error work mode %d!", __work_mode);
            break;
        }
        rt_thread_mdelay(200);
        _show_time_count++;
        if (_show_time_count >= 15)
        {
            change_work_mode_in_show_time();
            _show_time_count = 0;
        }
    }
}
static void nixie_tube_anti_posion(struct tm *p)
{
    static rt_bool_t anti_posion_flag = 0;
    if ((p->tm_sec == 59) && (anti_posion_flag == 0))
    {
        anti_posion_flag = 1;
        do
        {
            set_left_nixie_cube_number(temp_count);
            set_right_nixie_cube_number(temp_count);
            temp_count++;
            if (temp_count == 11)
            {
                temp_count = 0;
            }
            rt_thread_mdelay(30);
        } while (temp_count != 0);
    }
    if ((p->tm_sec == 0) && (anti_posion_flag == 1))
    {
        anti_posion_flag = 0;
    }
}

static void set_pomodoro_to_default(void)
{
    pomodoro.on_or_off = 0;
    pomodoro.start_time_stamp = 0;
    pomodoro.stop_time_stamp = 0;
    pomodoro.is_in_study_time = 0;
    pomodoro.is_in_rest_time = 0;
    pomodoro.is_complete_circular = 0;
    pomodoro.total_circular_count = 0;
}

void start_pomodoro_mode(void)
{
    time_t temp_timep;
    pomodoro.on_or_off = 1;
    time(&temp_timep);
    pomodoro.start_time_stamp = temp_timep;
    if (second_flickers_timer != RT_NULL)
        rt_timer_start(second_flickers_timer);
}
void stop_pomodoro_mode(void)
{
    time_t temp_timep;
    pomodoro.on_or_off = 0;
    time(&temp_timep);
    pomodoro.stop_time_stamp = temp_timep;
    if (second_flickers_timer != RT_NULL)
        rt_timer_stop(second_flickers_timer);
    set_left_nixie_cube_dot(0);
    set_right_nixie_cube_dot(0);
}

static void work_mode_in_pomodoro(void)
{
    time_t timep;
    time_t pomodoro_timep;
    struct tm *p;

    time(&timep);
    p = localtime(&timep);

    if (pomodoro.on_or_off == 0)
    {
        set_left_nixie_cube_number(0);
        set_right_nixie_cube_number(0);
    }
    else
    {
        pomodoro_timep = timep - pomodoro.start_time_stamp;
        if (pomodoro_timep <= 99)
        {
            pomodoro.is_in_study_time = 1;
            pomodoro.is_in_rest_time = 0;
            set_left_nixie_cube_number(pomodoro_timep / 10 % 10);
            set_right_nixie_cube_number(pomodoro_timep % 10);
        }
        else
        {
            set_left_nixie_cube_number(pomodoro_timep / 60 / 10 % 10);
            set_right_nixie_cube_number(pomodoro_timep / 60 % 10);
        }
        if ((pomodoro_timep >= 25 * 60) && (pomodoro_timep <= 30 * 60))
        {
            if ((pomodoro_timep == 25 * 60) && (pomodoro.is_in_study_time == 1))
            {
                beep(3, 500, 50, 4000);
            }
            pomodoro.is_in_study_time = 0;
            pomodoro.is_in_rest_time = 1;
            if ((timep - 25 * 60 - pomodoro.start_time_stamp) <= 99)
            {
                set_left_nixie_cube_number((timep - 25 * 60 - pomodoro.start_time_stamp) / 10 % 10);
                set_right_nixie_cube_number((timep - 25 * 60 - pomodoro.start_time_stamp) % 10);
            }
            else
            {
                set_left_nixie_cube_number((timep - 25 * 60 - pomodoro.start_time_stamp) / 60 / 10 % 10);
                set_right_nixie_cube_number((timep - 25 * 60 - pomodoro.start_time_stamp) / 60 % 10);
            }
        }
        else if (pomodoro_timep >= 30 * 60)
        {
            if ((pomodoro_timep == 30 * 60) && (pomodoro.is_in_rest_time == 1))
            {
                inc_pomodoro_count();
                beep(5, 500, 50, 4000);
            }
            pomodoro.is_in_study_time = 0;
            pomodoro.is_in_rest_time = 0;
            pomodoro.on_or_off = 0;
            pomodoro.stop_time_stamp = timep;
            pomodoro.is_complete_circular = 1;
        }
    }
}

static void work_mode_in_num_counter(void)
{
    set_left_nixie_cube_number(_count_num / 10 % 10);
    set_right_nixie_cube_number(_count_num % 10);
}
void increase_num_counter(void)
{
    _count_num++;
    if (_count_num >= 100)
    {
        _count_num = 0;
    }
}

static void work_mode_in_show_time(void)
{
    time_t timep;
    struct tm *p;
    if (get_work_mode() == WORK_MODE_SHOW_TIME)
    {
        time(&timep);
        p = localtime(&timep);
        if (_show_time_mode == WORK_MODE_SHOW_TIME_HOUR)
        {
            set_left_nixie_cube_dot(1);
            set_right_nixie_cube_dot(0);
            set_left_nixie_cube_number(p->tm_hour / 10 % 10);
            set_right_nixie_cube_number(p->tm_hour % 10);
        }
        else if (_show_time_mode == WORK_MODE_SHOW_TIME_MIN)
        {
            set_left_nixie_cube_dot(1);
            set_right_nixie_cube_dot(1);
            set_left_nixie_cube_number(p->tm_min / 10 % 10);
            set_right_nixie_cube_number(p->tm_min % 10);
        }
        else if (_show_time_mode == WORK_MODE_SHOW_TIME_SEC)
        {
            set_left_nixie_cube_dot(0);
            set_right_nixie_cube_dot(1);
            set_left_nixie_cube_number(p->tm_sec / 10 % 10);
            set_right_nixie_cube_number(p->tm_sec % 10);
        }
    }
}
void change_work_mode_in_show_time(void)
{
    _show_time_mode++;
    if (_show_time_mode > WORK_MODE_SHOW_TIME_SEC)
    {
        _show_time_mode = WORK_MODE_SHOW_TIME_HOUR;
    }
}

uint8_t get_work_mode(void)
{
    return __work_mode;
}
void set_work_mode(uint8_t mode)
{
    __work_mode = mode;
}

/* 定时器 超时函数 */
static void second_flickers_call(void *parameter)
{
    if (get_work_mode() == WORK_MODE_POMODORO)
    {
        static rt_bool_t bool = 0;
        if (pomodoro.is_in_rest_time)
        {
            set_right_nixie_cube_dot(bool);
        }
        else if (pomodoro.is_in_study_time)
        {
            set_left_nixie_cube_dot(bool);
        }
        bool = ~bool;
    }
}

int work_mode_thread_init(void)
{

    /* 创建定时器 1  周期定时器 */
    second_flickers_timer = rt_timer_create("gpio_refresh_timer", second_flickers_call,
                                            RT_NULL, 500,
                                            RT_TIMER_FLAG_PERIODIC);
    /* 初始化线程 1，名称是 work_mode_thread，入口是 work_mode_entry */
    rt_thread_init(&work_mode_thread,
                   "work_mode_thread",
                   work_mode_entry,
                   RT_NULL,
                   &work_mode_thread_stack[0],
                   sizeof(work_mode_thread_stack),
                   THREAD_PRIORITY - 1, THREAD_TIMESLICE);
    rt_thread_startup(&work_mode_thread);

    return 0;
}
INIT_APP_EXPORT(work_mode_thread_init);
